Advanced Debugging
About AdvDbg Consult Train Services Products Tools Community Contact  
欢迎光临 高端调试 登录 | 注册 | FAQ
 
  ACPI调试
Linux内核调试
Windows内核调试
 
  调试战役
调试原理
新工具观察
 
  Linux
Windows Vista
Windows
 
  Linux驱动
WDF
WDM
 
  PCI Express
PCI/PCI-X
USB
无线通信协议
 
  64位CPU
ARM
IA-32
  CPU Info Center
 
  ACPI标准
系统认证
Desktop
服务器
 
  Embedded Linux
嵌入式开发工具
VxWorks
WinCE
嵌入式Windows
 
  格蠹调试套件(GDK)
  格蠹学院
  小朱书店
  老雷的微博
  《软件调试》
  《格蠹汇编》
  《软件调试(第二版)》
沪ICP备11027180号-1

Windows内核调试

帖子发起人: Thomson   发起时间: 2009-09-10 20:44 下午   回复: 3

Print Search
帖子排序:    
   2009-09-10, 20:44 下午
Thomson 离线,最后访问时间: 2013/3/31 11:42:42 Thomson

发帖数前10位
注册: 2008-07-03
发 贴: 211
KiUserCallbackDispatch和KiUserCallbackDispatcher有没有区别?
Reply Quote
看名字挺相近的,不知道有没有什么区别. 都在ntdll里面.

IP 地址: 已记录   报告
   2009-09-11, 12:44 下午
WANGyu 离线,最后访问时间: 2012/9/10 3:34:00 王宇

发帖数前10位
男
注册: 2007-05-08
发 贴: 306
Re: KiUserCallbackDispatch和KiUserCallbackDispatcher有没有区别?
Reply Quote
兄台都玩这么高级的呀...

我几个平台都看了一遍,始终没有找到 KiUserCallbackDispatch,后来搜了一下,敢情是 x64 的啊?不晓得了..

x64 xp:   ntdll!KiUserCallbackDispatch:
00000000`77ef3160 488b4c2420         mov     rcx,qword ptr [rsp+20h]
00000000`77ef3165 8b542428           mov     edx,dword ptr [rsp+28h]
00000000`77ef3169 448b44242c         mov     r8d,dword ptr [rsp+2Ch]
00000000`77ef316e 65488b042560000000 mov     rax,qword ptr gs:[60h]
00000000`77ef3177 4c8b4858           mov     r9,qword ptr [rax+58h]
00000000`77ef317b 43ff14c1           call    qword ptr [r9+r8*8]

看功能似乎和 KiUserCallbackDispatcher 类似:

1: kd> u ntdll!KiUserCallbackDispatcher
ntdll!KiUserCallbackDispatcher:
7c92ead0 83c404          add     esp,4
7c92ead3 5a              pop     edx
7c92ead4 64a118000000    mov     eax,dword ptr fs:[00000018h]
7c92eada 8b4030          mov     eax,dword ptr [eax+30h]
7c92eadd 8b402c          mov     eax,dword ptr [eax+2Ch]
7c92eae0 ff1490          call    dword ptr [eax+edx*4]
7c92eae3 33c9            xor     ecx,ecx
7c92eae5 33d2            xor     edx,edx
7c92eae7 cd2b            int     2Bh
7c92eae9 cc              int     3

KiUserCallbackDispatcher 的流程就是 先 fs:[00000018h] 取到 _TEB,再取 _TEB._PEB(+0x030),之后取 _PEB.KernelCallbackTable(+0x02c),这是一个 Callback 派遣表:

   ......
   +0x028 EnvironmentUpdateCount : 1
   +0x02c KernelCallbackTable : 0x77d12970
   +0x030 SystemReserved   : [1] 0
   ......

1: kd> ln 0x77d12970
(77d12970)   USER32!apfnDispatch   |  (77d12af8)   USER32!szEMIKey
Exact matches:
    USER32!apfnDispatch =

1: kd> dd 0x77d12970
77d12970  77d3f534 77d583ac 77d1b390 77d1e613
77d12980  77d58365 77d58566 77d30a9a 77d5883b
77d12990  77d3f6e2 77d58708 77d1e7e2 77d58746
77d129a0  77d4fc0c 77d58784 77d58784 77d585a6
77d129b0  77d4f37c 77d1d2bc 77d21a95 77d1d1b3
77d129c0  77d3dc44 77d1d65c 77d1d1b3 77d585f8
77d129d0  77d5865f 77d3fe2d 77d1dca1 77d1dca1
77d129e0  77d32d09 77d588d0 77d58fee 77d582de

换成 C 的伪代码是这样:

VOID
KiUserCallbackDispatcher(
    __in PVOID CallbackArgument
    __in ULONG CallbackIndex
    )
{
    NTSTATUS Status;
    ULONG    ReturnStatus;
    PPEB     Peb;

    //
    // Note that a custom calling convention is used, such that all arguments are
    // passed on the stack, starting at [rsp+20] (on x64).  No register arguments
    // are used on x64 platforms.
    //

    //
    // Make the call to the specified kernel mode to user mode callback.  The set
    // of callback routines is stored in an array pointed to by the
    // "KernelCallbackTable" member of the PEB.
    //
    // Each callback takes a single argument, which is typically a structure
    // pointer.  Most callbacks are in fact actually sub-dispatchers for several
    // different callbacks that share the same calling convention after the
    // callback arguments are unpacked from the structure pointer.
    //
    // In the case of a Wow64 process, the Wow64 layer will have installed a set
    // of shadow trampoline function pointers in the PEB to facilitate the
    // necessary conversion of the callback argument.
    //


    Peb          = NtCurrentPeb();
    ReturnStatus = Peb->KernelCallbackTable[ CallbackIndex ]( CallbackArgument );

    //
    // If the callback did not explicitly return to kernel mode, then do so now.
    // Note that this is not the typical case, as all User32 callbacks should
    // call NtCallbackReturn directly.
    //


    Status = NtCallbackReturn(
        0,
        0,
        ReturnStatus
        );

    //
    // NtCallbackReturn should never return to us.  If it did so, then something
    // has gone very wrong.
    //


    for (;;)
        RtlRaiseStatus( Status );
}

微软的源码是汇编写的,注释很清楚,一并列出参考:

        page
        subttl  "User Callback Dispatcher"
;++
;
; VOID
; KiUserCallbackDispatcher (
;    IN ULONG ApiNumber,
;    IN PVOID InputBuffer,
;    IN ULONG INputLength
;    )
;
; Routine Description:
;
;    This routine is entered on a callout from kernel mode to execute a
;    user mode callback function. All arguments for this function have
;    been placed on the stack.
;
; Arguments:
;
;    ApiNumber - Supplies the API number of the callback function that is
;        executed.
;
;    InputBuffer - Supplies a pointer to the input buffer.
;
;    InputLength - Supplies the input buffer length.
;
; Return Value:
;
;    This function returns to kernel mode.
;
;--
cPublicProc _KiUserCallbackDispatcher, 3
.FPO (0, 0, 0, 0, 0, 0)

        add     esp,4                   ; skip over return address
        pop     edx                     ; get address of callback function

                                        ; get peb pointer from teb
        mov     eax,fs:[PcTeb]
        mov     eax,[eax].TebPeb
        mov     eax,[eax].PebKernelCallbackTable    ; get address of callback table

        call    [eax+edx*4]             ; call specified function

;
; If a return from the callback function occurs, then the output buffer
; address and length are returned as NULL.
;


        xor     ecx,ecx                 ; clear output buffer address
ifdef BUILD_WOW6432
        stdCall _ZwCallbackReturn,
else
        xor     edx,edx                 ; clear output buffer length
        int     02bH                    ; return from callback
endif
        int     3                       ; break if return occurs

stdENDP _KiUserCallbackDispatcher

IP 地址: 已记录   报告
   2009-09-12, 10:29 上午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: KiUserCallbackDispatch和KiUserCallbackDispatcher有没有区别?
Reply Quote
x64使用所谓基于表的异常分发方法, 下面博客中的系列文章详细介绍过:
http://www.nynaeve.net/?p=105
OSR的这篇文章也值得看一下:
http://www.osronline.com/article.cfm?id=469
写"软件调试"时本来打算介绍了,后来担心篇幅...

IP 地址: 已记录   报告
   2009-09-12, 22:29 下午
Thomson 离线,最后访问时间: 2013/3/31 11:42:42 Thomson

发帖数前10位
注册: 2008-07-03
发 贴: 211
Re: KiUserCallbackDispatch和KiUserCallbackDispatcher有没有区别?
Reply Quote
谢谢两位,这确实是x64下面的, 看到这两个名字这么接近,果然功能相近.
IP 地址: 已记录   报告
高端调试 » 软件调试 » Windows内核调试 » KiUserCallbackDispatch和KiUserCallbackDispatcher有没有区别?

 
Legal Notice Privacy Statement Corporate Governance Corporate Governance
(C)2004-2020 ADVDBG.ORG All Rights Reserved.